<!-- 下拉刷新指示器
@color  可选 定义指示器圆环颜色
@bgcolor  可选 定义指示器背景颜色
@immediate false 可选 是否立即执行一次
@v-model 控制刷新实例显示
@ @refresh 必填 数据刷新方法
@target 选填，挂载节点的id
 -->
<template>
  <div class="refresh" ref="refresh">
    <teleport to="#refresh">
      <div id="indicator" :style="{top:indicatorY+'PX', backgroundColor:getBgcolor}">
        <span><span :style="rotate(-180,true)"></span></span><span><span :style="rotate(-180)"></span></span>
        <i :style="{backgroundColor:getBgcolor}"></i>
      </div>
    </teleport>
    <slot></slot>
  </div>
</template>

<script>
import { computed, onMounted, ref, watch } from 'vue'
export default{
  props: {
    modelValue: {
      type: Boolean,
      default: false
    },
    color: String,
    bgcolor: String,
    immediate: {
      type: Boolean,
      default: false
    },
    target:[String]
  },
  setup(params, ctx){
    const refresh = ref(null)
    let start_y = ref(0)
    let scroll_y = ref(0)
    let fontSize = 0
    let hideMode = 0
    let refresh_key = false
    let canTouch = false
    let request = ctx.attrs.onRefresh 

    if(typeof request != 'function'){
      console.error('FRefresh: request method no setting or not a function')
      request = function() {
        setTimeout(() => {
          ctx.emit('update:modelValue', false)
        },500)
      }
    }

    const getColor = computed(()=>{
      return params.color || Less.indicatorColor
    })
    const getBgcolor = computed(()=>{
      return params.bgcolor || Less.mainbgc
    })
    const indicatorY = computed(()=>{
      let _dist = scroll_y.value - start_y.value
      if(_dist < 0){
        return 0
      } else {
        return _dist < 2.0*fontSize?_dist:2.0*fontSize+ (_dist-2.0*fontSize)/3
      }
    })
    
    
    function initRefresh () { //初始化指示器
      let $body = $(params.target ? refresh.value.querySelector(`#${params.target}`) : refresh.value), $indicator = $('#indicator')
      $body.on('touchstart', (e) => {
        e.stopPropagation()
        canTouch = $body.scrollTop() < 3 ? true : false
        if (e.targetTouches.length == 1 && !refresh_key && canTouch) {
          start_y.value = e.targetTouches[0].pageY
        }
      }).on('touchmove', (e) => {
        e.stopPropagation()
        if (e.targetTouches.length == 1 && !refresh_key && canTouch) {
          let touch = e.targetTouches[0]
          if (touch.pageY - start_y.value > 0) {
            scroll_y.value = touch.pageY
          }
        }
      }).on('touchend', (e) => {
        e.stopPropagation()
        if(!refresh_key && canTouch && scroll_y.value - start_y.value >= 2.0 * fontSize){
          refresh_key = true
          $indicator.addClass('transition')
          scroll_y.value = 2.0 * fontSize + start_y.value
          $indicator.one("webkitTransitionEnd", function(e) {
            $(this).addClass('rotate')
            ctx.emit('update:modelValue', true)
            request()
          })
        } else if(!refresh_key && canTouch && scroll_y.value - start_y.value >= 0) {
          $indicator.addClass('transition')
          hideRefresh()
        }
      })
    }

    function hideRefresh () { //隐藏下拉指示器
      let $indicator = $('#indicator'), _step = (scroll_y.value - start_y.value) / 10
      $indicator.one("webkitTransitionEnd", (e) => {
        $indicator.removeClass('transition')
        $indicator.removeClass('rotate')
        refresh_key = false
        hideMode = 0
      })
      hideMode = scroll_y.value
      let _timer = () => {
        setTimeout(() => {
          hideMode -= _step
          if(hideMode > 0) {
            _timer()
          } else {
            hideMode = 0
          }
        }, 30)
      }
      _timer()
      scroll_y.value = 0
    }

    function rotate (deg, key) {
      let dist = (hideMode || scroll_y.value) - start_y.value
      dist = (dist > 0 ? dist : 0)
      dist = Math.round(dist / (2.0 * fontSize) * 270)
      if (key) {
        if (Math.abs(dist) < 180){
          dist = 0
        } else {
          dist = dist - 180
          dist = Math.abs(dist) > 90 ? 90 : dist
        }
      } else {
        dist = dist <= 0 ? 0 : dist
        dist = dist > 180 ? 180 : dist
      }
      deg += dist || 0
      return {
        '-webkit-transform': `rotate(${deg}deg)`,
        'transform': `rotate(${deg}deg)`,
        'backgroundColor': getColor.value
      }
    }

    watch(() => params.modelValue, (_new, _old)=>{
      if (!_new) {
        hideRefresh()
      }
    })

    onMounted(()=>{
      let _fontSize = $('html').css('font-size')
      fontSize = Number(_fontSize.slice(0, _fontSize.length - 2))
      initRefresh()
    })

    params.immediate && request()

    return {
      refresh,
      getBgcolor,
      indicatorY,
      rotate
    }
  },
}
</script>
<style lang="less" scoped="">
.refresh {
  height: 100%;
  position: relative;
  overflow-y: auto;
}
#indicator {
  position: fixed;
  width: 36PX;
  height: 36PX;
  left: 50%;
  top: 0;
  margin-left: -18PX;
  margin-top: -45PX;
  border-radius: 50%;
  overflow: hidden;
  box-shadow: 0 0 6PX rgba(0,0,0,.3);
  z-index: 100;
  &.transition {
    transition: top ease-in 300ms;
  }
  > span {
    position: absolute;
    top: 50%;
    left: 50%;
    height: 24PX;
    width: 12PX;
    transform: translateY(-50%) translateX(-100%);
    overflow: hidden;
    &:last-of-type {
      transform: translateY(-50%) translateX(0%);
      span {
        right: 0;
        transform: rotate(-90deg);
        clip:rect(0,auto,auto,12PX);
      }
    }
    span {
      position: absolute;
      width: 24PX;
      height: 24PX;
      border-radius: 50%;
      transform: rotate(-180deg);
      clip:rect(0,12PX,auto,auto);
    }
  }
  > i {
    position: absolute;
    width: 19PX;
    height: 19PX;
    left: 50%;
    top: 50%;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    z-index: 1;
  }
 }

.rotate {
  animation: rotate linear 800ms infinite;
}
@-webkit-keyframes rotate{
  0% {transform: rotate(0deg);}
  100% {transform: rotate(360deg);}
}
@keyframes rotate{
  0% {transform: rotate(0deg)}
  100% {transform: rotate(360deg);}
}
</style>
